package cn.zuo.utils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.math.BigInteger;
import java.util.*;
/**
 * @Author 白白旧维
 * @Date 2021/7/7 11:13
 */
public class PPKeyFactory {

    private static List<BigInteger> pqs = new ArrayList<>();//pq库
    private static List<BigInteger> es = new ArrayList<>();//e库
    private static List<Map<String,BigInteger>> key = new ArrayList<>();//密钥库
    private static Map<String,BigInteger> randomKey = new HashMap<>();

    public static Map<String, BigInteger> getRandomKey() {
        return randomKey;
    }

    static {
        init_pqs();

        init_es();

        create_key_all();

        //initOneRandomKey();

    }

    private static void init_pqs()  {
        try {
            File file = new File("d:/pqs.txt");
            FileReader fr = new FileReader(file);
            BufferedReader br = new BufferedReader(fr);
            String len = "";
            while((len=br.readLine())!=null){
                BigInteger bi = new BigInteger(len);
                pqs.add(bi);
            }
        }catch (Exception ex){
            ex.printStackTrace();
        }//可以选择关闭流


    }

    private static void init_es(){
        try {
            File file = new File("d:/es.txt");
            FileReader fr = new FileReader(file);
            BufferedReader br = new BufferedReader(fr);
            String len = "";
            while((len=br.readLine())!=null){
                BigInteger bi = new BigInteger(len);
                es.add(bi);
            }
        }catch (Exception ex){
            ex.printStackTrace();
        }//可以选择关闭流
    }


    private static Map<String,BigInteger> create_key_one(BigInteger p,BigInteger q,BigInteger e){
//        long n = p*q;
        BigInteger n = p.multiply(q);
//        long phi = (p-1)*(q-1);
        BigInteger phi = p.subtract(new BigInteger("1")).multiply(q.subtract(new BigInteger("1")));

        //①：计算中间栈
        Stack<BigInteger> stack = new Stack<>();
//        long s_pre = e;
        BigInteger s_pre = e;//
//        long s_last = phi%s_pre;
        BigInteger s_last = phi.mod(s_pre);
//        stack.push(phi/s_pre);
        stack.push(phi.divide(s_pre));

        while(s_last.compareTo(new BigInteger("0"))==1){
//            long t_s_last = s_last;
            BigInteger t_s_last = s_last;//
//            s_last = s_pre%t_s_last;
            s_last = s_pre.mod(t_s_last);
            if(s_last.compareTo(new BigInteger("0"))==0){
                break;
            }
            stack.push(s_pre.divide(t_s_last));
            s_pre = t_s_last;//

        }

        //②：计算中间d
        ArrayList<BigInteger> arrayList = new ArrayList<>();
        arrayList.add(new BigInteger("0"));
        arrayList.add(new BigInteger("1"));
        int index = 2;

        int len = stack.size();
        while(!stack.isEmpty()){
            BigInteger next = arrayList.get(index-1).multiply(stack.pop()).add(arrayList.get(index-2));
            arrayList.add(next);
            index++;
        }


        //③：由奇偶计算最终d
        BigInteger d = arrayList.get(index-1);
        if(len%2==0){
        }else{
            d = phi.subtract(d);
        }

        Map<String,BigInteger> map = new HashMap<>();
        map.put("e",e);
        map.put("n",n);
        map.put("d",d);
        return map;
    }

    private static void create_key_all(){//生成密钥库
        for(int i=0;i<pqs.size();i++){
            for(int j=0;j<i;j++){
                for(int k=0;k<es.size();k++){
                    BigInteger p = pqs.get(i);
                    BigInteger q = pqs.get(j);
                    BigInteger e = es.get(k);
                    if(p.compareTo(q)!=0){//p和q不等，生成密钥
                        key.add(create_key_one(p,q,e));
                    }
                }
            }
        }
        System.out.println("固定密钥库生成完毕！！");
    }

    public static List<Map<String,BigInteger>> getAllKey(){//获取密钥库中的所有密钥
        return key;
    }


    public static Map<String,BigInteger> getOneKey(Long timestamp){//获取一个密钥
        int index = (int) (Math.abs(timestamp)%key.size());
        return key.get(index);
    }


    private static void initOneRandomKey(){
        long be = System.currentTimeMillis();

        //随机生成一个强素数p,10^200
        BigInteger p = StrongPrimes.get_strongPrime_one(System.currentTimeMillis()
                ,"100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
                ,"500000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");

        //随机生成一个强素数q
        BigInteger q = StrongPrimes.get_strongPrime_one(System.currentTimeMillis()
                ,"100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
                ,"500000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");

        Integer ei = Math.abs(new Random().nextInt()%20);

        randomKey = create_key_one(p,q, es.get(ei));

        p=null;
        q=null;//销毁p、q

        long af = System.currentTimeMillis();
        System.out.println("随机密钥生成耗时："+(af-be)+"ms");//随机密钥生成耗时：433060ms

    }



}